﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
/************************************************
*********** LDAP Mandatory Libraries ************
************************************************/
using System.Configuration; 
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices.Protocols;

namespace LDAP_Manager
{
    public class LDAPManager
    {
        #region Fields and Properties
        /// <summary>
        /// Directory entry field
        /// </summary>
        private DirectoryEntry directoryEntry;
        /// <summary>
        /// Active Directory Path
        /// </summary>
        private string LDAPPath
        {
            get
            {
                return LDAP_Manager.Properties.Settings.Default.LDAPPath;
            }
        }
        /// <summary>
        /// Active Directory UserName
        /// </summary>
        private string LDAPUser
        {
            get
            {
                return LDAP_Manager.Properties.Settings.Default.LDAPUser;
            }
        }
        /// <summary>
        /// Active Directory Password
        /// </summary>
        private string LDAPPassword
        {
            get
            {
                return LDAP_Manager.Properties.Settings.Default.LDAPPassword;
            }
        }
        /// <summary>
        /// Active Directory Domain
        /// </summary>
        private String LDAPDomain
        {
            get
            {
                return LDAP_Manager.Properties.Settings.Default.LDAPDomain;
            }
        }
        /// <summary>
        /// Initializing my directory entry.
        /// </summary>
        private DirectoryEntry SearchRoot
        {
            get
            {
                if (directoryEntry == null)
                {
                    directoryEntry = new DirectoryEntry(LDAPPath, LDAPUser, LDAPPassword, AuthenticationTypes.Secure);
                }
                return directoryEntry;
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// This function returns an user from Active Directory given the Full Name
        /// </summary>
        /// <param name="userName">User Full Name</param>
        /// <returns>User Information</returns>
        public ADUser GetUserByFullName(string userName)
        {
            try
            {
                directoryEntry = null;

                DirectorySearcher directorySearch = new DirectorySearcher(SearchRoot);
                directorySearch.Filter = String.Format("(&(objectClass=user)(cn={0}))", userName);
                SearchResult results = directorySearch.FindOne();

                if (results != null)
                {
                    DirectoryEntry user = new DirectoryEntry(LDAPPath, LDAPUser, LDAPPassword);
                    return ADUser.GetUser(user);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception EX)
            {
                return null;
            }
        }
        /// <summary>
        /// This function returns an user from Active Directory given the Login Name
        /// </summary>
        /// <param name="userName">User Login Name</param>
        /// <returns>User Information</returns>
        public ADUser GetUserByLoginName(string userName)
        {
            try
            {
                directoryEntry = null;

                DirectorySearcher directorySearch = new DirectorySearcher(SearchRoot);
                directorySearch.Filter = String.Format("(&(objectClass=user)(SAMAccountName={0}))", userName);
                SearchResult results = directorySearch.FindOne();

                if (results != null)
                {
                    DirectoryEntry user = new DirectoryEntry(LDAPPath, LDAPUser, LDAPPassword);
                    return ADUser.GetUser(user);
                }
                else
                {
                    return null;
                }
            }
            catch (Exception EX)
            {
                return null;
            }
        }
        /// <summary>
        /// This function returns all the users that belongs to a group
        /// </summary>
        /// <param name="groupName">Name of the group</param>
        /// <returns>User Information</returns>
        public List<ADUser> GetUserFromGroup(string groupName)
        {
            List<ADUser> userList = new List<ADUser>();

            try
            {
                directoryEntry = null;

                DirectorySearcher directorySearch = new DirectorySearcher(SearchRoot);
                directorySearch.Filter = String.Format("(&(objectClass=group)(SAMAccountName={0}))", groupName);
                SearchResult result = directorySearch.FindOne();

                if (result != null)
                {
                    DirectoryEntry deGroup = new DirectoryEntry(LDAPPath, LDAPUser, LDAPPassword);
                    System.DirectoryServices.PropertyCollection pCol = deGroup.Properties;
                    int Count = pCol["member"].Count;

                    for (int i = 0; i < Count; i++)
                    {
                        string resPath = result.Path;
                        string[] pathNavigate = resPath.Split("CN".ToCharArray());
                        resPath = pathNavigate[0];
                        string objpath = pCol["member"][i].ToString();
                        string path = resPath + objpath;


                        DirectoryEntry user = new DirectoryEntry(path, LDAPUser, LDAPPassword);
                        ADUser userobj = ADUser.GetUser(user);
                        userList.Add(userobj);
                        user.Close();
                    }
                }
                return userList;
            }
            catch (Exception EX)
            {
                return userList;
            }
        }
        /// <summary>
        /// This function returns all the users with the same firstname
        /// </summary>
        /// <param name="fName">First Name</param>
        /// <returns>User Information</returns>
        public List<ADUser> GetUsersByFirstName(string fName)
        {

            //UserProfile user;
            List<ADUser> userlist = new List<ADUser>();
            string filter = "";

            directoryEntry = null;
            DirectorySearcher directorySearch = new DirectorySearcher(SearchRoot);
            directorySearch.Asynchronous = true;
            directorySearch.CacheResults = true;
            //directorySearch.Filter = "(&(objectClass=user)(SAMAccountName=" + userName + "))";
            filter = string.Format("(givenName={0}*", fName);
            //filter = "(&(objectClass=user)(objectCategory=person)" + filter + ")";
            filter = string.Format("(&(objectClass=user)(objectCategory=person)(givenName={0}*))", fName);


            directorySearch.Filter = filter;

            SearchResultCollection userCollection = directorySearch.FindAll();
            foreach (SearchResult users in userCollection)
            {
                DirectoryEntry userEntry = new DirectoryEntry(users.Path, LDAPUser, LDAPPassword);
                ADUser userInfo = ADUser.GetUser(userEntry);


                userlist.Add(userInfo);
            }

            directorySearch.Filter = "(&(objectClass=group)(SAMAccountName=" + fName + "*))";
            SearchResultCollection results = directorySearch.FindAll();
            if (results != null)
            {

                foreach (SearchResult r in results)
                {
                    DirectoryEntry deGroup = new DirectoryEntry(r.Path, LDAPUser, LDAPPassword);
                    // ADUserDetail dhan = new ADUserDetail();
                    ADUser agroup = ADUser.GetUser(deGroup);
                    userlist.Add(agroup);
                }

            }
            return userlist;
        }
        /// <summary>
        /// This function add an user to the specified group
        /// </summary>
        /// <param name="userlogin">User Login Name</param>
        /// <param name="groupName">Group Name</param>
        /// <returns>Return true if the user was added otherwise returns false</returns>
        public bool AddUserToGroup(string userlogin, string groupName)
        {
            try
            {
                directoryEntry = null;
                ADManager admanager = new ADManager(LDAPDomain, LDAPUser, LDAPPassword);
                admanager.AddUserToGroup(userlogin, groupName);
                return true;
            }
            catch (Exception EX)
            {
                return false;
            }
        }
        /// <summary>
        /// This function removes an user from the specified group  
        /// </summary>
        /// <param name="userlogin">User login name</param>
        /// <param name="groupName">Group Name</param>
        /// <returns>Return true if the user was succesfully removed otherwise returns false</returns>
        public bool RemoveUserToGroup(string userlogin, string groupName)
        {
            try
            {
                directoryEntry = null;
                ADManager admanager = new ADManager("xxx", LDAPUser, LDAPPassword);
                admanager.RemoveUserFromGroup(userlogin, groupName);
                return true;
            }
            catch (Exception EX)
            {
                return false;
            }
        }
        /// <summary>
        /// This function tries to log the user provided in the paramters
        /// </summary>
        /// <param name="userName">User Name</param>
        /// <param name="password">Password</param>
        /// <returns>The User information if is sucessfull, null if not</returns>
        public ADUser LogUser(string userName, string password)
        {
            try
            {
                directoryEntry = new DirectoryEntry(LDAPPath);
                directoryEntry.AuthenticationType = AuthenticationTypes.Secure;
                directoryEntry.Username = userName;
                directoryEntry.Password = password;
                return ADUser.GetUser(directoryEntry);
            }
            catch (Exception EX)
            {
                return null;
            }
        }
        /// <summary>
        /// This function add's an user to the Active Directory
        /// </summary>
        /// <param name="user">User information</param>
        /// <param name="password">Password</param>
        /// <returns>True if the user was created, false otherwise</returns>
        public bool AddUser(ADUser user, string password)
        {
            DirectoryEntry newUser = new DirectoryEntry(LDAPPath);
            bool result = false;

            using (newUser)
            {
                DirectoryEntry content = newUser.Children.Add(String.Format("CN={0}", user.FirstName), "user");

                using (content)
                {
                    content.Properties[ADProperties.FIRSTNAME].Add(user.FirstName);
                    content.Properties[ADProperties.LASTNAME].Add(user.LastName);
                    content.Properties[ADProperties.CITY].Add(user.City);
                    content.Properties[ADProperties.COMPANY].Add(user.Company);
                    content.Properties[ADProperties.COUNTRY].Add(user.Country);
                    content.Properties[ADProperties.DEPARTMENT].Add(user.Department);
                    content.Properties[ADProperties.EMAILADDRESS].Add(user.EmailAddress);
                    content.Properties[ADProperties.EXTENSION].Add(user.Extension);
                    content.Properties[ADProperties.FAX].Add(user.Fax);
                    content.Properties[ADProperties.HOMEPHONE].Add(user.HomePhone);
                    content.Properties[ADProperties.LOGINNAME].Add(user.LoginName);
                    content.Properties[ADProperties.MANAGER].Add(user.ManagerName);
                    content.Properties[ADProperties.MIDDLENAME].Add(user.MiddleName);
                    content.Properties[ADProperties.MOBILE].Add(user.Mobile);
                    content.Properties[ADProperties.POSTALCODE].Add(user.PostalCode);
                    content.Properties[ADProperties.STATE].Add(user.State);
                    content.Properties[ADProperties.STREETADDRESS].Add(user.StreetAddress);
                    content.Properties[ADProperties.TITLE].Add(user.Title);
                    int val = (int)content.Properties["userAccountControl"].Value;
                    newUser.Properties["userAccountControl"].Value = val | 0x80000;
                    content.Invoke("SetPassword", new object[] { password });
                    content.CommitChanges();

                    result = true;
                }

                return result;
            }
        }
        /// <summary>
        /// This method resets the user password
        /// </summary>
        /// <param name="userName">User Name</param>
        /// <param name="password">Password</param>
        public void ResetPassword(string userName, string password)
        {
            DirectoryEntry uEntry = new DirectoryEntry(userName);
            uEntry.Invoke("SetPassword", new object[] { password });
            uEntry.Properties["LockOutTime"].Value = 0; //unlock account

            uEntry.Close();
        }
        #endregion
    }
}
